﻿using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;

namespace ShopB2C.Core.Helpers
{
    public class ThumbImageHelper
    {
        /// <summary>
        /// 生成缩略图
        /// </summary>
        /// <param name="maxWidth">缩略图宽</param>
        /// <param name="maxHeight">缩略图高</param>
        /// <param name="img">进行重绘的图片来源 , System.Drawing.Image类型</param>
        /// <param name="isHighQulity">是否输出高品质</param>
        /// <returns>包含图片的内存流</returns>
        private static MemoryStream ThumbPhoto(int thumbWidth , int thumbHeight , Image img , bool isHighQulity)
        {
            // 计算缩放比例或大小
            float x , y , w , h;

            if (thumbHeight < 1 | thumbWidth < 1)
                throw new Exception("至少一个参数没有指定");

            // 自动裁减图片

            #region 调整大小

            if (img.Width > img.Height)
            {
                if (img.Height > thumbHeight)
                {
                    h = thumbHeight;
                    w = (int)((float)thumbHeight / (float)img.Height * (float)img.Width);
                }
                else
                {
                    w = thumbWidth;
                    h = (float)thumbWidth / (float)img.Width * (float)img.Height;
                }

            }
            else
            {
                if (img.Width > thumbWidth)
                {
                    w = thumbWidth;
                    h = (float)thumbWidth / (float)img.Width * (float)img.Height;
                }
                else
                {
                    h = thumbHeight;
                    w = (int)((float)thumbHeight / (float)img.Height * (float)img.Width);
                }
            }

            #endregion

            x = (thumbWidth - w) / 2;
            y = (thumbHeight - h) / 2;

            #region 开始绘图

            // 缩略图大小
            System.Drawing.Bitmap b = new Bitmap(thumbWidth , thumbHeight);
            // 新建画布
            Graphics g = Graphics.FromImage(b);
            // 设置画布的描绘质量
            g.CompositingQuality = CompositingQuality.HighQuality;
            // 设置高质量插值法
            g.InterpolationMode = InterpolationMode.High;
            // 设置高质量,低速度呈现平滑程度
            g.SmoothingMode = SmoothingMode.HighQuality;
            // 清空画布并以白色填充
            g.Clear(Color.White);
            // 画图
            g.DrawImage(img ,
                x == 0 ? x - 1 : x ,
                y == 0 ? y - 1 : y ,
                x == 0 ? w + 1 : w ,
                y == 0 ? h + 1 : h);

            try
            {
                MemoryStream ms = new MemoryStream();
                if (isHighQulity)
                {
                    // 以下代码为保存图片时，设置压缩质量
                    EncoderParameters encoderParams = new EncoderParameters();
                    long[] quality = new long[1];
                    quality[0] = 100;

                    EncoderParameter encoderParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality , quality);
                    encoderParams.Param[0] = encoderParam;

                    //获得包含有关内置图像编码解码器的信息的 ImageCodecInfo 对象。
                    ImageCodecInfo[] arrayICI = ImageCodecInfo.GetImageEncoders();
                    ImageCodecInfo jpegICI = null;
                    for (int i = 0 ; i < arrayICI.Length ; i++)
                    {
                        if (arrayICI[i].FormatDescription.Equals("JPEG"))
                        {
                            jpegICI = arrayICI[i]; //设置JPEG编码
                            break;
                        }
                    }
                    if (jpegICI != null)
                    {
                        b.Save(ms , jpegICI , encoderParams);
                    }
                    else
                    {
                        b.Save(ms , img.RawFormat);
                    }
                }
                else
                {
                    b.Save(ms , img.RawFormat);
                }
                return ms;
            }
            catch
            {
                return null;
            }
            finally
            {
                b.Dispose();
                g.Dispose();
            }

            #endregion
        }
        /// <summary>
        /// 生成等比例缩略图,图片将被缩小的指定的大小，当图片为长方形时，图片将按照比较大的那条边来缩放
        /// </summary>
        /// <param name="maxWidth">缩略图宽</param>
        /// <param name="maxHeight">缩略图高</param>
        /// <param name="filepath">图片路径，来此磁盘的绝对路径</param>
        /// <param name="isFixed">是否进行图片修正</param>
        /// <param name="isHighQulity">是否输出高品质</param>
        /// <returns>包含图片的内存流</returns>
        public static MemoryStream ThumbPhoto(int maxWidth , int maxHeight , string filePath , bool isHighQulity)
        {
            Image img = LoadImage(filePath);
            // 修正图片大小
            maxWidth = maxWidth <= 0 ? img.Width : maxWidth;
            maxHeight = maxHeight <= 0 ? img.Height : maxHeight;

            maxWidth = img.Width <= maxWidth ? img.Width : maxWidth;
            maxHeight = img.Height <= maxHeight ? img.Height : maxHeight;

            float rate = (float)img.Width / (float)img.Height;
            // 计算等比例缩放的目标图大小
            if (img.Width <= img.Height)
            {
                maxWidth = (int)(((float)maxHeight * rate) + 0.5);
            }
            else
            {
                maxHeight = (int)(((float)maxWidth / rate) + 0.5);
            }

            return ThumbPhoto(maxWidth , maxHeight , img , isHighQulity);
        }
        /// <summary>
        /// 按照给定的长宽比生成缩略图，生成的缩略图最大高和宽不会超过指定的高和宽,最终图片尺寸以图片的比较大的那条边为基准
        /// 但是生成的缩略图长宽之比和提供的maxWidth和maxHeight比例一致，
        /// </summary>
        /// <param name="maxWidth">最大宽</param>
        /// <param name="maxHeight">最大高</param>
        /// <param name="isHighQulity">高品质</param>
        /// <returns>包含图片的类存流</returns>
        public static MemoryStream RateCuteThumbPhoto(int maxWidth , int maxHeight , string filePath , bool isHighQulity)
        {
            Image img = LoadImage(filePath);
            float rate = (float)maxWidth / (float)maxHeight;
            if (img.Width > img.Height)
            {
                maxWidth = img.Width;
                maxHeight = (int)(((float)img.Width / rate) + 0.5);
            }
            else
            {
                maxHeight = img.Height;
                maxWidth = (int)(((float)img.Height * rate + 0.5));
            }
            return ThumbPhoto(maxWidth , maxHeight , img , isHighQulity);
        }
        /// <summary>
        /// 强制裁剪图片到指定大小，如果图片和裁剪区域大小不匹配，将从图片正中间裁剪
        /// </summary>
        /// <param name="maxWidth">图片宽</param>
        /// <param name="maxHeight">图片高</param>
        /// <param name="filePath">文件路径</param>
        /// <param name="isFixed">自动修正图片,如果图片比例与指定大小不匹配，将被填充白边以裁剪，否则强制从正中间裁剪</param>
        /// <param name="isHighQulity">高品质</param>
        /// <returns>包含图片的类存流</returns>
        public static MemoryStream CuteThumbPhoto(int thumbWidth , int thumbHeight , string filePath , bool isFixed , bool isHighQulity)
        {
            Image img = isFixed ?
                Image.FromStream(RateCuteThumbPhoto(thumbWidth , thumbHeight , filePath , isHighQulity))
                : LoadImage(filePath);
            // 2次裁剪到指定大小
            return ThumbPhoto(thumbWidth , thumbHeight , img , isHighQulity);

        }
        /// <summary>
        /// 装载图片并且防止图片被锁定
        /// http://support.microsoft.com/kb/311754/EN-US/
        /// </summary>
        /// <param name="photoPath">图片路径</param>
        /// <returns>Image</returns>
        private static Image LoadImage(string photoPath)
        {
            using (FileStream stream = new FileStream(photoPath , FileMode.Open , FileAccess.Read))
            {
                using (BinaryReader reader = new BinaryReader(stream))
                {
                    // 取得所有的图片数据   
                    byte[] buffer = new byte[stream.Length];
                    reader.Read(buffer , 0 , (int)stream.Length);
                    // 然后创建一个内存中的 Stream 对象去生成图片   
                    // 这样文件就不会被锁定了   
                    using (MemoryStream ms = new MemoryStream(buffer))
                    {
                        return Image.FromStream(ms);
                    }
                }
            }
        }
    }
}
